//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//********************************************************* 

using System;
using System.Diagnostics;

namespace Microsoft.TridentWordAddIn.Common
{
    /// <summary>
    /// Reroutes logging from Trace to log4net
    /// </summary>
    public class EnterpriseLoggingTraceListener : TraceListener
    {
        /// <summary>
        /// Gets a value indicating whether the trace listener is thread safe.
        /// </summary>
        /// <value></value>
        /// <returns>true if the trace listener is thread safe; otherwise, false. The default is false.</returns>
        public override bool IsThreadSafe
        {
            get { return true; }
        }

        /// <summary>
        /// When overridden in a derived class, writes the specified message to the listener you create in the derived class.
        /// </summary>
        /// <param name="message">A message to write.</param>
        public override void Write(string message)
        {
            this.Write((object)message, null);
        }

        /// <summary>
        /// Writes the value of the object's <see cref="M:System.Object.ToString"></see> method to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"></see> class.
        /// </summary>
        /// <param name="o">An <see cref="T:System.Object"></see> whose fully qualified class name you want to write.</param>
        public override void Write(object o)
        {
            this.Write(o, null);
        }

        /// <summary>
        /// Writes a category name and the value of the object's <see cref="M:System.Object.ToString"></see> method to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"></see> class.
        /// </summary>
        /// <param name="o">An <see cref="T:System.Object"></see> whose fully qualified class name you want to write.</param>
        /// <param name="category">A category name used to organize the output.</param>
        public override void Write(object o, string category)
        {
            TraceLevel tracelevel = (category == null) ? TraceLevel.Info : GetTraceLevel(category);
            try
            {
                switch (tracelevel)
                {
                    case TraceLevel.Error:
                        Logger.Error(o);
                        break;
                    case TraceLevel.Warning:
                        Logger.Warn(o);
                        break;
                    case TraceLevel.Verbose:
                        Logger.Debug(o);
                        break;
                    case TraceLevel.Info:
                    default:
                        Logger.Info(o);
                        break;
                }
            }
            catch (Exception)
            {
                // logging should never throw exceptions
            }
        }

        /// <summary>
        /// Gets the trace level.
        /// </summary>
        /// <param name="category">The category.</param>
        /// <returns>The trace level associated with the category. By default returns Info</returns>
        private static TraceLevel GetTraceLevel(string category)
        {
            TraceLevel tracelevel;
            try
            {
                tracelevel = (TraceLevel)Enum.Parse(typeof(TraceLevel), category);
            }
            catch
            {
                //We just set the tracelevel to info
                tracelevel = TraceLevel.Info;
            }

            return tracelevel;
        }

        /// <summary>
        /// Writes a category name and a message to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"></see> class.
        /// </summary>
        /// <param name="message">A message to write.</param>
        /// <param name="category">A category name used to organize the output.</param>
        public override void Write(string message, string category)
        {
            this.Write((object)message, category);
        }

        /// <summary>
        /// When overridden in a derived class, writes a message to the listener you create in the derived class, followed by a line terminator.
        /// </summary>
        /// <param name="message">A message to write.</param>
        public override void WriteLine(string message)
        {
            this.Write(message);
        }

        /// <summary>
        /// Writes the value of the object's <see cref="M:System.Object.ToString"></see> method to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"></see> class, followed by a line terminator.
        /// </summary>
        /// <param name="o">An <see cref="T:System.Object"></see> whose fully qualified class name you want to write.</param>
        public override void WriteLine(object o)
        {
            this.Write(o);
        }

        /// <summary>
        /// Writes a category name and the value of the object's <see cref="M:System.Object.ToString"></see> method to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"></see> class, followed by a line terminator.
        /// </summary>
        /// <param name="o">An <see cref="T:System.Object"></see> whose fully qualified class name you want to write.</param>
        /// <param name="category">A category name used to organize the output.</param>
        public override void WriteLine(object o, string category)
        {
            this.Write(o, category);
        }

        /// <summary>
        /// Writes a category name and a message to the listener you create when you implement the <see cref="T:System.Diagnostics.TraceListener"></see> class, followed by a line terminator.
        /// </summary>
        /// <param name="message">A message to write.</param>
        /// <param name="category">A category name used to organize the output.</param>
        public override void WriteLine(string message, string category)
        {
            this.Write(message, category);
        }
    }
}

